#include<stdio.h>
#include<stdlib.h>
#include<sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>


int main(int args, const char * argv[]){

	if(args < 3){
		perror("less args");
		exit(0);
	}

	int sockfd;
	int ret;
	struct sockaddr_in addr;
	socklen_t addrlen = sizeof(struct sockaddr_in);
	// BUFSIZ 8192
	char buf[BUFSIZ] = {0};  
	//1. 创建套接字：IPV4、UDP
	sockfd = socket(AF_INET, SOCK_DGRAM, 0);
	if(sockfd < 0){
		perror("socket");
		exit(0);
	}

	//地址快速重用：允许在同一端口上启动新的服务器，即使之前的服务器实例还没有完全关闭
	int flag = 1, len = sizeof(int);
	if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &flag, len) == -1){
		perror("setsockopt");
		exit(1);
	}

	//2. 绑定通信结构体
	addr.sin_family = AF_INET;
	//atoi:将字符串转化成整形数据
	addr.sin_port = htons(atoi(argv[2]));
#if 1
	if (inet_aton(argv[1], &addr.sin_addr) == 0) {
		fprintf(stderr, "Invalid address\n");
		exit(EXIT_FAILURE);
	}
#else
	addr.sin_addr.s_addr = inet_addr(argv[1]);
#endif
	if(bind(sockfd, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) == -1){
		perror("bind");
		exit(0);
	}

	//3. 读取客户端上送的请求数据
	while(1){
		memset(buf, 0, BUFSIZ);
		//这里与TCP通信不同，TCP通信中若结束了客户端进程，read函数不阻塞，会一直循环执行
		//UDP通信中，即使结束了客户端进程，服务端进程依然在recvfrom函数阻塞。
		ret = recvfrom(sockfd, buf, BUFSIZ, 0, (struct sockaddr *)&addr, &addrlen);
		printf("buf : %s\n", buf);
		/*
		if(ret == 0){
			//当把客户端关闭时，返回的就是0,此时一直打印No data,
			//所以后面加上break 退出循环
			printf("No data\n");
			break;
		}else if(ret < 0){
			//出错
			break;
		}else {
			printf("buf : %s", buf);
		}*/
	}

	//4. 关闭套接字
	close(sockfd);
	return 0;
}
